package com.duojuhe.coremodule.sms.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.TypeReference;
import com.duojuhe.cache.SystemDictCache;
import com.duojuhe.common.annotation.DataScopeFilter;
import com.duojuhe.common.annotation.KeyLock;
import com.duojuhe.common.bean.UserTokenInfoVo;
import com.duojuhe.common.enums.SystemEnum;
import com.duojuhe.common.extend.form.utils.FormAttributeUtils;
import com.duojuhe.coremodule.sms.enums.SmsEnum;
import com.duojuhe.common.exception.base.DuoJuHeException;
import com.duojuhe.common.result.ErrorCodes;
import com.duojuhe.common.result.PageResult;
import com.duojuhe.common.result.ServiceResult;
import com.duojuhe.common.utils.idgenerator.UUIDUtils;
import com.duojuhe.common.utils.jsonutils.JsonUtils;
import com.duojuhe.common.utils.page.PageHelperUtil;
import com.duojuhe.coremodule.BaseService;
import com.duojuhe.coremodule.sms.entity.SmsChannel;
import com.duojuhe.coremodule.sms.entity.SmsIsp;
import com.duojuhe.coremodule.sms.entity.SmsSendTask;
import com.duojuhe.coremodule.sms.entity.SmsTemplate;
import com.duojuhe.coremodule.sms.mapper.SmsChannelMapper;
import com.duojuhe.coremodule.sms.mapper.SmsIspMapper;
import com.duojuhe.coremodule.sms.mapper.SmsSendTaskMapper;
import com.duojuhe.coremodule.sms.mapper.SmsTemplateMapper;
import com.duojuhe.coremodule.sms.pojo.channel.*;
import com.duojuhe.common.extend.form.attribute.Attribute;
import com.duojuhe.common.extend.form.attribute.AttributeEvent;
import com.duojuhe.common.extend.form.attribute.AttributeParameter;
import com.duojuhe.coremodule.sms.service.SmsChannelService;
import com.duojuhe.coremodule.system.entity.SystemDict;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import javax.annotation.Resource;
import org.springframework.stereotype.Service;
import tk.mybatis.mapper.entity.Example;

import java.util.*;
import java.util.stream.Collectors;

@Slf4j
@Service
public class SmsChannelServiceImpl  extends BaseService implements SmsChannelService {
    @Resource
    private SystemDictCache systemDictCache;
    @Resource
    private SmsIspMapper smsIspMapper;
    @Resource
    private SmsChannelMapper smsChannelMapper;
    @Resource
    private SmsSendTaskMapper smsSendTaskMapper;
    @Resource
    private SmsTemplateMapper smsTemplateMapper;
    /**
     * 【分页查询】根据条件查询短信发送渠道list
     * @param req
     * @return
     */
    @DataScopeFilter
    @Override
    public ServiceResult<PageResult<List<QuerySmsChannelPageRes>>> querySmsChannelPageResList(QuerySmsChannelPageReq req) {
        PageHelperUtil.orderByAndStartPage(req, "sort desc,createTime desc, channelId desc");
        List<QuerySmsChannelPageRes> list = smsChannelMapper.querySmsChannelPageResList(req);
        list.forEach(this::setHandleSmsChannelDictNameColor);
        return PageHelperUtil.returnServiceResult(req, list);
    }

    /**
     * 【查询详情】根据短信发送渠道id查询渠道详情
     * @param req
     * @return
     */
    @Override
    public ServiceResult<QuerySmsChannelRes> querySmsChannelResByChannelId(SmsChannelIdReq req) {
        QuerySmsChannelRes res = smsChannelMapper.querySmsChannelResByChannelId(req.getChannelId());
        if (res==null){
            return ServiceResult.fail(ErrorCodes.PARAM_ERROR);
        }
        if (StringUtils.isNotBlank(res.getIspAttribute())){
            //请求参数的填写的值
            List<AttributeParameter> ispAttributeParameters = JSON.parseObject(res.getChannelIspAttribute(), new TypeReference<ArrayList<AttributeParameter>>(){});
            //请求参数转成map
            Map<String, AttributeParameter> parameterMap = ispAttributeParameters.stream().collect(Collectors.toMap(AttributeParameter::getKey, a -> a));
            AttributeEvent ispAttributeEvent = JSON.parseObject(res.getIspAttribute(), new TypeReference<AttributeEvent>(){});
            List<Attribute> attributeList = FormAttributeUtils.buildAttributeList(parameterMap,ispAttributeEvent.getAttribute());
            res.setIspAttributeList(attributeList);
        }
        return ServiceResult.ok(res);
    }


    /**
     * 【保存】短信发送渠道
     * @param req
     * @return
     */
    @Override
    public ServiceResult saveSmsChannel(SaveSmsChannelReq req) {
        //当前登录人
        UserTokenInfoVo userTokenInfoVo = getCurrentLoginUserInfoDTO();
        //部门id
        String createDeptId = userTokenInfoVo.getCreateDeptId();
        //检查渠道名称
        checkSmsChannelName(req.getChannelName(),userTokenInfoVo.getTenantId());
        //检查服务商是否存在
        SmsIsp smsIsp = getSmsIspByIspId(req.getIspId());
        //检查属性
        String channelIspAttribute = buildChannelIspAttribute(req.getChannelIspAttribute(),smsIsp);
        //当前时间
        Date nowDate = new Date();
        //当前登录人id
        String userId = userTokenInfoVo.getUserId();
        //渠道id
        String channelId = UUIDUtils.getUUID32();
        //渠道编码
        String channelCode = UUIDUtils.getSequenceNo();
        SmsChannel channel = new SmsChannel();
        channel.setChannelId(channelId);
        channel.setIspId(req.getIspId());
        channel.setChannelCode(channelCode);
        channel.setChannelName(req.getChannelName());
        channel.setChannelIspAttribute(channelIspAttribute);
        channel.setRemark(req.getRemark());
        channel.setStatusCode(req.getStatusCode());
        channel.setCreateTime(nowDate);
        channel.setCreateUserId(userId);
        channel.setUpdateTime(nowDate);
        channel.setUpdateUserId(userId);
        channel.setSort(req.getSort());
        channel.setCreateDeptId(createDeptId);
        channel.setTenantId(userTokenInfoVo.getTenantId());
        channel.setBuiltIn(SystemEnum.YES_NO.NO.getKey());
        smsChannelMapper.insertSelective(channel);
        return ServiceResult.ok(channelId);
    }


    /**
     * 【修改】短信发送渠道
     * @param req
     * @return
     */
    @KeyLock(lockKeyParts = "channelId")
    @Override
    public ServiceResult updateSmsChannel(UpdateSmsChannelReq req) {
        SmsChannel channelOld = smsChannelMapper.selectByPrimaryKey(req.getChannelId());
        if (channelOld == null) {
            return ServiceResult.fail(ErrorCodes.PARAM_ERROR);
        }
        if (SystemEnum.YES_NO.YES.getKey().equals(channelOld.getBuiltIn())) {
            return ServiceResult.fail(ErrorCodes.SMS_CHANNEL_NOT_UPDATE);
        }
        //检查渠道名称
        if (!req.getChannelName().equals(channelOld.getChannelName())){
            checkSmsChannelName(req.getChannelName(),channelOld.getTenantId());
        }
        //检查是否存在待发送的短信任务
        checkWaitingSmsSendTaskByChannelId(channelOld.getChannelId());
        //检查服务商是否存在
        SmsIsp smsIsp = getSmsIspByIspId(channelOld.getIspId());
        //检查属性
        String channelIspAttribute = buildChannelIspAttribute(req.getChannelIspAttribute(),smsIsp);
        //当前时间
        Date nowDate = new Date();
        //当前登录人
        UserTokenInfoVo userTokenInfoVo = getCurrentLoginUserInfoDTO();
        //当前登录人id
        String userId = userTokenInfoVo.getUserId();
        SmsChannel channel = new SmsChannel();
        channel.setChannelId(channelOld.getChannelId());
        channel.setChannelName(req.getChannelName());
        channel.setChannelIspAttribute(channelIspAttribute);
        channel.setRemark(req.getRemark());
        channel.setStatusCode(req.getStatusCode());
        channel.setUpdateTime(nowDate);
        channel.setUpdateUserId(userId);
        channel.setSort(req.getSort());
        smsChannelMapper.updateByPrimaryKeySelective(channel);
        return ServiceResult.ok(req.getChannelId());
    }

    /**
     * 【删除】根据短信发送渠道id删除渠道
     * @param req
     * @return
     */
    @KeyLock(lockKeyParts = "channelId")
    @Override
    public ServiceResult deleteSmsChannelByChannelId(SmsChannelIdReq req) {
        String channelId = req.getChannelId();
        SmsChannel channelOld = smsChannelMapper.selectByPrimaryKey(channelId);
        if (channelOld == null) {
            return ServiceResult.fail(ErrorCodes.PARAM_ERROR);
        }
        if (SystemEnum.YES_NO.YES.getKey().equals(channelOld.getBuiltIn())) {
            return ServiceResult.fail(ErrorCodes.SMS_CHANNEL_NOT_DELETE);
        }
        //检查是否存在关联模板
        isExistSmsTemplateByChannelId(channelId);
        //检查是否存在待发送的短信任务
        checkWaitingSmsSendTaskByChannelId(channelId);
        //删除渠道
        smsChannelMapper.deleteByPrimaryKey(channelId);
        return ServiceResult.ok(channelId);
    }




    /*====================================私有方法beg==============================================**/

    /**
     * 【私有方法，辅助其他接口方法使用】 检查是否存在待发送的短信任务
     */
    private void checkWaitingSmsSendTaskByChannelId(String channelId) {
        if (StringUtils.isBlank(channelId)){
            throw new DuoJuHeException(ErrorCodes.PARAM_ERROR);
        }
        Example example = new Example(SmsSendTask.class);
        Example.Criteria criteria = example.createCriteria();
        criteria.andEqualTo("channelId", channelId);
        criteria.andEqualTo("taskStatusCode", SmsEnum.SmsSendTaskStatus.SMS_WAITING_EXECUTE.getKey());
        if (smsSendTaskMapper.selectByExample(example).size()>0){
            throw new DuoJuHeException(ErrorCodes.SMS_CHANNEL_WAITING_SEND_TASK_EXIST);
        }
    }

    /**
     * 【私有方法，辅助其他接口方法使用】 检查是否存在关联的短信模板
     */
    private void isExistSmsTemplateByChannelId(String channelId) {
        if (StringUtils.isBlank(channelId)){
            throw new DuoJuHeException(ErrorCodes.PARAM_ERROR);
        }
        Example example = new Example(SmsTemplate.class);
        Example.Criteria criteria = example.createCriteria();
        criteria.andEqualTo("channelId", channelId);
        if (smsTemplateMapper.selectByExample(example).size()>0){
            throw new DuoJuHeException(ErrorCodes.SMS_CHANNEL_EXIST_SMS_TEMPLATE_ERROR);
        }
    }

    /**
     * 检查服务商参数格式
     * @param channelIspAttribute
     */
    private String buildChannelIspAttribute(String channelIspAttribute,SmsIsp smsIsp){
        if (StringUtils.isBlank(channelIspAttribute)){
            throw new DuoJuHeException(ErrorCodes.SMS_ISP_ATTRIBUTE_FORMAT_WRONG);
        }
        if (smsIsp==null){
            throw new DuoJuHeException(ErrorCodes.SMS_ISP_ATTRIBUTE_FORMAT_WRONG);
        }
        if (!JsonUtils.isJson(channelIspAttribute)) {
            throw new DuoJuHeException(ErrorCodes.SMS_ISP_ATTRIBUTE_FORMAT_WRONG);
        }
        //短信服务商属性参数
        String ispAttribute = smsIsp.getIspAttribute();
        if (!JsonUtils.isJson(ispAttribute)) {
            throw new DuoJuHeException(ErrorCodes.SMS_ISP_ATTRIBUTE_FORMAT_WRONG);
        }
        //把原有服务商属性参数转成 对象
        AttributeEvent ispAttributeEvent = JSON.parseObject(ispAttribute, new TypeReference<AttributeEvent>(){});
        if (ispAttributeEvent==null){
            throw new DuoJuHeException(ErrorCodes.SMS_ISP_ATTRIBUTE_FORMAT_WRONG);
        }
        //服务商的属性参数
        List<Attribute> attributeList = ispAttributeEvent.getAttribute();
        //请求参数的填写的值
        List<AttributeParameter> ispAttributeParameters = JSON.parseObject(channelIspAttribute, new TypeReference<ArrayList<AttributeParameter>>(){});
        //请求参数转成map
        Map<String, AttributeParameter> parameterMap = ispAttributeParameters.stream().collect(Collectors.toMap(AttributeParameter::getKey, a -> a));
        //返回的参数
        List<AttributeParameter> ispAttributeRes = FormAttributeUtils.buildAttributeParameterList(parameterMap,attributeList);
        return JSON.toJSONString(ispAttributeRes);
    }


    /**
     * 获取短信服务商
     * @param ispId
     */
    private SmsIsp getSmsIspByIspId(String ispId){
        if (StringUtils.isBlank(ispId)){
            throw new DuoJuHeException(ErrorCodes.SMS_ISP_NOT_EXIST);
        }
        SmsIsp smsIsp = smsIspMapper.selectByPrimaryKey(ispId);
        if (smsIsp==null || !SystemEnum.STATUS.NORMAL.getKey().equals(smsIsp.getStatusCode())){
            throw new DuoJuHeException(ErrorCodes.SMS_ISP_NOT_EXIST);
        }
        return smsIsp;
    }

    /**
     * 【私有方法，辅助其他接口方法使用】 查询短信渠道是否已经存在
     */
    private void checkSmsChannelName(String channelName,String tenantId) {
        if (StringUtils.isBlank(channelName)||StringUtils.isBlank(tenantId)){
            throw new DuoJuHeException(ErrorCodes.SMS_CHANNEL_NAME_EXIST);
        }
        Example example = new Example(SmsChannel.class);
        Example.Criteria criteria = example.createCriteria();
        criteria.andEqualTo("channelName", channelName);
        criteria.andEqualTo("tenantId", tenantId);
        if(smsChannelMapper.selectByExample(example).size()>0){
            throw new DuoJuHeException(ErrorCodes.SMS_CHANNEL_NAME_EXIST);
        }
    }


    /**
     * 处理返回值的数据字典
     * @param res
     */
    private void setHandleSmsChannelDictNameColor(HandleSmsChannelDictNameColorRes res) {
        if (res==null){
            return;
        }
        SystemDict dictStatus = systemDictCache.getSystemDictByDictCode(res.getStatusCode());
        res.setStatusName(dictStatus.getDictName());
        res.setStatusColor(dictStatus.getDictColor());

        SystemDict ispStatus = systemDictCache.getSystemDictByDictCode(res.getIspStatusCode());
        res.setIspStatusName(ispStatus.getDictName());
        res.setIspStatusColor(ispStatus.getDictColor());
    }
}
